<?php
/**
 * Slince music finder library
 * @author Tao <taosikai@yeah.net>
 */
namespace Slince\MusicFinder\QQ;

use GuzzleHttp\Psr7\Request;
use Slince\MusicFinder\Entity\Album;
use Slince\MusicFinder\Entity\Singer;
use Slince\MusicFinder\Entity\Song;
use Slince\MusicFinder\Exception\SearchException;
use Slince\MusicFinder\HttpAwareFinder;

class Finder extends HttpAwareFinder
{
    const SEARCH_ENDPOINT = 'http://c.y.qq.com/soso/fcgi-bin/client_search_cp';

    const SEARCH_REFERER = 'http://y.qq.com/portal/search.html';

    const USER_AGENT  = 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1';

    const SONG_ENDPOINT = 'http://i.y.qq.com/s.plcloud/fcgi-bin/fcg_list_songinfo_cp.fcg';

    const SONG_REFERER = 'http://data.music.qq.com/playsong.html?songmid={songId}';

    const ALBUM_COVER = 'http://y.gtimg.cn/music/photo_new/T002R300x300M000{albumId}.jpg';

    const SOURCE_URL =  'http://isure.stream.qqmusic.qq.com/C100{songId}.m4a?fromtag=32';

    const PLAY_URL = 'https://y.qq.com/n/yqq/song/{songId}.html';

    /**
     * {@inheritdoc}
     */
    public function search($name, $page = 1, $limit = 10)
    {
        $request = new Request('GET', static::SEARCH_ENDPOINT, [
            'Referer' => static::SEARCH_REFERER,
            'X-Requested-With' => 'XMLHttpRequest',
            'User-Agent' => static::USER_AGENT
        ]);
        $response = $this->getHttpClient()->send($request, [
            'query' => [
                'w' => $name,
                'p' => $page,
                'n' => $limit,
                'format' => 'json'
            ]
        ]);
        $json = \GuzzleHttp\json_decode($response->getBody(), true);
        return static::buildSearchResults($json);
    }

    /**
     * {@inheritdoc}
     */
    public function find($id)
    {
        $request = new Request('GET', static::SONG_ENDPOINT, [
            'Referer' => str_replace('{songId}', $id, static::SONG_REFERER),
            'X-Requested-With' => 'XMLHttpRequest',
            'User-Agent' => static::USER_AGENT
        ]);
        $response = $this->getHttpClient()->send($request, [
            'query' => [
                'midlist' => $id
            ]
        ]);
        $json = \GuzzleHttp\json_decode($response->getBody(), true);
        if (empty($json['data'])) {
            throw new SearchException('Got a bad response');
        }
        return static::buildSong($json['data'][0]);
    }

    /**
     * Converts the search data to song entity array
     * @param array $json
     * @return Song[]
     */
    protected static function buildSearchResults($json)
    {
        if ($json['code'] != 0 || empty($json['data']['song']['list'])) {
            throw new SearchException('Got a bad response');
        }
        return array_map(function($songData){
            return static::buildSong($songData);
        }, $json['data']['song']['list']);
    }

    /**
     * Builds the song entity
     * @param array $songData
     * @return Song
     */
    protected static function buildSong($songData)
    {
        $singer = new Singer($songData['singer'][0]['mid'], $songData['singer'][0]['name']);
        $album = new Album($songData['albummid'], $songData['albumname'], str_replace('{albumId}', $songData['albummid'], static::ALBUM_COVER));
        $sourceUrl = str_replace('{songId}', $songData['songmid'], static::SOURCE_URL);
        $playUrl = str_replace('{songId}', $songData['songmid'], static::PLAY_URL);
        return new Song($songData['songmid'], $songData['songname'], $sourceUrl, $playUrl, $singer, $album);
    }
}